import {
  ConnectionPositionPair,
  HorizontalConnectionPos,
  VerticalConnectionPos,
} from '@angular/cdk/overlay';

class PositionMapPair {
  originX: HorizontalConnectionPos;
  originY: VerticalConnectionPos;
  overlayX: HorizontalConnectionPos;
  overlayY: VerticalConnectionPos;
}

const createConnectionPositionPair = (pair: PositionMapPair): ConnectionPositionPair => {
  const {
    originX,
    originY,
    overlayX,
    overlayY,
  } =  pair;
  return new ConnectionPositionPair({originX, originY}, {overlayX, overlayY});
};

export type Direction = 'top' | 'topCenter' | 'topLeft' | 'topRight'
  | 'bottom' | 'bottomCenter' | 'bottomLeft' | 'bottomRight'
  | 'right' | 'rightTop' | 'rightBottom'
  | 'left' | 'leftTop' | 'leftBottom';

const _POSITION_MAP: {[key: string]: PositionMapPair} = {
  top: {
    originX : 'center',
    originY : 'top',
    overlayX: 'center',
    overlayY: 'bottom',
  },
  topCenter: {
    originX : 'center',
    originY : 'top',
    overlayX: 'center',
    overlayY: 'bottom',
  },
  topLeft: {
    originX : 'start',
    originY : 'top',
    overlayX: 'start',
    overlayY: 'bottom',
  },
  topRight: {
    originX : 'end',
    originY : 'top',
    overlayX: 'end',
    overlayY: 'bottom',
  },
  right: {
    originX : 'end',
    originY : 'center',
    overlayX: 'start',
    overlayY: 'center',
  },
  rightTop: {
    originX : 'end',
    originY : 'top',
    overlayX: 'start',
    overlayY: 'top',
  },
  rightBottom: {
    originX : 'end',
    originY : 'bottom',
    overlayX: 'start',
    overlayY: 'bottom',
  },
  bottom: {
    originX : 'center',
    originY : 'bottom',
    overlayX: 'center',
    overlayY: 'top',
  },
  bottomCenter: {
    originX : 'center',
    originY : 'bottom',
    overlayX: 'center',
    overlayY: 'top',
  },
  bottomLeft: {
    originX : 'start',
    originY : 'bottom',
    overlayX: 'start',
    overlayY: 'top',
  },
  bottomRight: {
    originX : 'end',
    originY : 'bottom',
    overlayX: 'end',
    overlayY: 'top',
  },
  left: {
    originX : 'start',
    originY : 'center',
    overlayX: 'end',
    overlayY: 'center',
  },
  leftTop: {
    originX : 'start',
    originY : 'top',
    overlayX: 'end',
    overlayY: 'top',
  },
  leftBottom: {
    originX : 'start',
    originY : 'bottom',
    overlayX: 'end',
    overlayY: 'bottom',
  },
};

export const POSITION_MAP: {[key: string]: ConnectionPositionPair} = Object.keys(_POSITION_MAP).reduce((accum, key) => {
  accum[key] = createConnectionPositionPair(_POSITION_MAP[key]);
  return accum;
}, {});

export type Placement = 'top' | 'topCenter' | 'topLeft' | 'topRight'
  | 'bottom' | 'bottomCenter' | 'bottomLeft' | 'bottomRight'
  | 'right' | 'rightTop' | 'rightBottom'
  | 'left' | 'leftTop' | 'leftBottom';

export const DEFAULT_POPOVER_POSITIONS: ConnectionPositionPair[] = [
  POSITION_MAP[ 'top' ], POSITION_MAP[ 'right' ],
  POSITION_MAP[ 'bottom' ], POSITION_MAP[ 'left' ],
];

export const DEFAULT_PICKER_POSITIONS: ConnectionPositionPair[] = [
  POSITION_MAP['topLeft'], POSITION_MAP['bottomLeft'],
  POSITION_MAP['topRight'], POSITION_MAP['bottomRight'],
];

export const DEFAULT_CASCADE_POSITIONS: ConnectionPositionPair[] = [
  POSITION_MAP['rightTop'], POSITION_MAP['rightBottom'],
  POSITION_MAP['leftTop'], POSITION_MAP['leftBottom'],
];

/**
 * 保持展示方向的Position生成策略，以bottomLeft为例该函数生成如下6个方向，保持的展示方向为纵向
 * ["bottomLeft", "topLeft", "bottom", "bottomRight", "top", "topRight"]
 *
 * @param direction 初始方向
 */
export const composePositionSet = (direction: Direction) => {
  const directions: Direction[] = [direction];
  const placements = ['left', 'right', 'top', 'bottom'];
  const pIdx = placements.findIndex((p) => direction.indexOf(p) === 0);
  const placement = placements[pIdx];

  // 生成相反Direction，对于比如topLeft这样的情况在纵向无法显示全，那优先考虑bottomLeft的可能性而不是其他的bottomXXX
  const oppositiPlacement = pIdx === 0 || pIdx === 2 ? placements[pIdx + 1] : placements[pIdx - 1];
  const rest = `${direction}`.slice(placement.length);
  const oppositeDir = `${oppositiPlacement}${rest}`;
  directions.push(oppositeDir as Direction);

  // 生成其余方向
  let connections = [];
  if (pIdx < 2) {
    connections = ['', 'Top', 'Bottom'];
  } else {
    connections = ['', 'Left', 'Right'];
  }
  [placement, oppositiPlacement].forEach((place) => {
    connections.forEach((conn) => {
      const dir = `${place}${conn}` as Direction;
      if (directions.indexOf(dir) === -1) {
        directions.push(dir);
      }
    });
  });
  return directions.map((dir) => POSITION_MAP[dir]);
};
